home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / mac / comm / revrdist.sit / RevRdist / RevRINIT src / RevRINIT.c
Encoding:
C/C++ Source or Header  |  1990-06-23  |  14.8 KB  |  634 lines  |  [TEXT/KAHL]

  1. /*
  2.  * RevRINIT.c - INIT to cause RevRdist to be run at system boot time
  3.  */
  4. #include <MacProto.h>
  5. #include <C_config.h>
  6. #include <asm.h>
  7. #include <HFS.h>
  8. #include "HyperXCmd.h"
  9. #include "rsrc.h"
  10.  
  11. /*
  12.  * Structure of startup header
  13.  */
  14. typedef unsigned char Str15[16];    /* short pascal string */
  15. struct startp {
  16.     Integer        startid;            /* id word */
  17.     ProcPtr        entryp;                /* boot code entry point */
  18.     Integer        version;            /* startup version */
  19.     Integer        azero;
  20.     Str15        sysname;            /* name of system resource file */
  21.     Str15        shellname;            /* name of system shell */
  22.     Str15        debuggername;        /* name of debugger file */
  23.     Str15        disassmname;        /* name of disassembler file */
  24.     Str15        startscreen;        /* name of startup screen image file */
  25.     Str15        startappl;            /* name of first program to run */
  26.     Str15        scrapname;            /* name of disk scrap file */
  27.     Integer        fcbcnt;                /* number of file control blocks */
  28.     Integer        eventcnt;            /* size of event queue */
  29.     Longint        heapsize1;            /* heap size on 128k system */
  30.     Longint        reserved;
  31.     Longint        heapsize2;            /* heap size on 512k system */
  32. };
  33. typedef struct startp startp_t;
  34. #define STARTID 'LK'                /* correct value of id word */
  35.     
  36. typedef unsigned char Str31[32];    /* path name component */
  37. typedef unsigned long u_long;
  38.  
  39. #define COPYPS(s,d)    BlockMove (s, d, (Size)(((s)[0]) + 1))    /* copy pas. str */
  40. #define    ZERO(s)        setmem ((char *)&(s), sizeof (s), 0)    /* zero struct */
  41.  
  42. /*
  43.  * Prototypes
  44.  */
  45. pascal void callback (void);
  46. static OSErr doFudge (Str31);
  47. static OSErr findAppl (Str31);
  48. static OSErr getPrefs (Str31, StringHandle *, Str31, Str31, Str31, Str31, Str31);
  49. static OSErr getPrefsName (Str31, Str31);
  50. extern void main (Handle);
  51. static OSErr mountsvr (Str31, Str31, Str31, Str31, Str31);
  52. static Handle ptoch (unsigned char *);
  53. extern void    setmem (char *p, unsigned n, char c);
  54. extern void ShowINIT (Integer);
  55. static void start (void);
  56.  
  57.  
  58. /*
  59.  *=========================================================================
  60.  * start () - routine given control by INIT 31
  61.  *    Must be first code in first file in project
  62.  *=========================================================================
  63.  */
  64. static
  65. void
  66. start ()
  67. {
  68.     asm
  69.     {
  70.         move.l    a0,-(sp)            /* pass handle to selves to main */
  71.         move.l    (a0),a4                /* set A4 to allow refs to globals */
  72.         jsr        main                /* call main routine */
  73.         move.l    (sp)+,a0            /* pop arg to restore stack */
  74.     }
  75. }
  76.  
  77.  
  78. extern unsigned char ApplScratch[12] : 0xa78;
  79.  
  80. /*
  81.  *=========================================================================
  82.  * main - main sequence
  83.  *=========================================================================
  84.  */
  85. void
  86. main (self)
  87.     Handle self;
  88. {
  89.     register OSErr result;
  90.     StringHandle master;            /* name of master folder on server */
  91.     Str31    applName;                /* name of RevRdist application */
  92.     Str31    prefName;                /* name of prefs file */
  93.     Str31    zoneName;                /* server zone name */
  94.     Str31    serverName;                /* name of server to use */
  95.     Str31    userName;                /* name to log on to server as */
  96.     Str31    serverVol;                /* server volume to user */
  97.     Str31    password;                /* user password on server */
  98.     CInfoPBRec    ci;                    /* for PBGetCatInfo call */
  99.     Str255    s;                        /* string temp */
  100.     Integer    volref;                    /* dummy for GetVol */
  101.  
  102.     HLock (self);
  103.     SetResLoad (true);                /* should already be true, but ... */
  104.     result = (FSFCBLen <= 0);        /* make sure HFS */
  105.     /*
  106.      * Find the RevRdist application
  107.      */
  108.     if (result == 0)
  109.         result = findAppl (applName);
  110.     /*
  111.      * Get the name of the preferences file from RevRdist
  112.      */
  113.     if (result == 0)
  114.         result = getPrefsName (applName, prefName);
  115.     /*
  116.      * Extract the preferences & check if it's time to run
  117.      */
  118.     master = 0;
  119.     if (result == 0)
  120.         result = getPrefs (prefName, &master,
  121.                     serverVol, zoneName, serverName, userName, password);
  122.     /*
  123.      * If the master folder is not currently available, try to mount it
  124.      */
  125.     if (result == 0)
  126.     {
  127.         ZERO (ci);
  128.         HLock ((Handle) master);
  129.         ci.dirInfo.ioNamePtr = *master;
  130.         result = PBGetCatInfo (&ci, false);
  131.         HUnlock ((Handle) master);
  132.         if (result
  133.             || (ci.dirInfo.ioFlAttrib & 0x10) == 0    /* if not folder */
  134.             || (ci.dirInfo.ioACUser & 0x03) != 0 )    /* if no access */
  135.         {
  136.             /*
  137.              * Be sure we don't try to unmount the boot volume
  138.              */
  139.             (void) GetVol (s, &volref);
  140.             if (RelString (s, serverVol, false, true))
  141.             {
  142.                 serverVol[++serverVol[0]] = ':';
  143.                 (void) UnmountVol (serverVol, 0);
  144.                 serverVol[0]--;
  145.                 result = mountsvr (serverVol, zoneName, serverName, userName, password);
  146.             }
  147.             else
  148.                 result = paramErr;
  149.         }
  150.     }
  151.     if (master)
  152.         DisposHandle ((Handle) master);
  153.     if (result == 0)
  154.         result = doFudge (applName);
  155.     HUnlock (self);
  156. }
  157.  
  158.  
  159.  
  160. /*
  161.  *=========================================================================
  162.  * callback () - dummy XCMD callback routine
  163.  *    should never be called
  164.  *=========================================================================
  165.  */
  166. pascal
  167. void
  168. callback ()
  169. {
  170. }
  171.  
  172.  
  173.  
  174. /*
  175.  *=========================================================================
  176.  * doFudge (ap) - modify memory copy of boot blocks to make RevRdist
  177.  *            application the "startup" application
  178.  * entry:    ap = name of RevRdist
  179.  * returns:    0 if all went well, 
  180.  *            <> 0 if boot blocks area looks fishy
  181.  *=========================================================================
  182.  */
  183. static
  184. OSErr
  185. doFudge (ap)
  186.     Str31    ap;
  187. {
  188. register unsigned char c;
  189. register startp_t *    startp;            /* ptr to boot param block */
  190.     long *        lp;                    /* pts into ApplScratch */
  191.  
  192.     /*
  193.      * Locate the memory copy of the system startup information
  194.      * Check that it appears intact.
  195.      * Replace the startup program name with RevRdist name
  196.      */
  197.     startp = (startp_t *) ((long)MemTop / 2);
  198.  
  199.     if (startp->startid != STARTID)
  200.         return 1;
  201.     if (startp->azero)
  202.         return 2;
  203. #define    CHECK(w, e)    if ((c = startp->w[0]) == 0 || c > 15) return (e)
  204.     CHECK (sysname, 3);
  205.     CHECK (shellname, 4);
  206.     CHECK (debuggername, 5);
  207.     CHECK (disassmname, 6);
  208.     CHECK (startscreen, 7);
  209.     CHECK (startappl, 8);
  210.     CHECK (scrapname, 9);
  211. #undef CHECK
  212.     if (startp->fcbcnt < 0)
  213.         return 10;
  214.     if (startp->eventcnt < 0)
  215.         return 11;
  216.     COPYPS (ap, startp->startappl);
  217.     lp = (long *)(ApplScratch + 8);
  218.     lp[0] = CREATOR;            /* leave a "note" for RevRdist */
  219.     return 0;
  220. }
  221.  
  222.  
  223.  
  224. /*
  225.  *=========================================================================
  226.  * findAppl (ap) - locate RevRdist application and return its name
  227.  * entry:    ap = Str31 to contain name
  228.  * returns:    0 on success, else OSErr
  229.  *=========================================================================
  230.  */
  231. static
  232. OSErr
  233. findAppl (ap)
  234.     Str31 ap;
  235. {
  236.     OSErr        error;
  237.     int            i;
  238.     Str255        name;
  239.     CInfoPBRec    ci;
  240.  
  241.     /*
  242.      * Search the current directory to find a file with the correct
  243.      * type (APPL) and CREATOR.
  244.      */
  245.     ZERO (ci);
  246.     ci.hFileInfo.ioNamePtr = name;
  247.     for (i = 1, error = 0; ! error; i++)
  248.     {
  249.         name[0] = 0;
  250.         ci.hFileInfo.ioDirID = 0;
  251.         ci.hFileInfo.ioFDirIndex = i;
  252.         error = PBGetCatInfo (&ci, false);
  253.         if (error == 0)
  254.         {
  255.             if (ci.hFileInfo.ioFlAttrib & 0x10)
  256.                 continue;            /* if directory */
  257.             if (ci.hFileInfo.ioFlFndrInfo.fdType == 'APPL'
  258.              && ci.hFileInfo.ioFlFndrInfo.fdCreator == CREATOR)
  259.             {
  260.                 if (name[0] > 15)
  261.                     continue;        /* ignore if unacceptable name */
  262.                 COPYPS (name, ap);
  263.                 break;
  264.             }
  265.         }
  266.     }
  267.     return error;
  268. }
  269.  
  270.  
  271.  
  272. /*
  273.  *=========================================================================
  274.  * getPrefs (pf, mf, sv, zn, sn, un, pw) - extract info from preferences file
  275.  * entry:    pf = name of preferences file
  276.  *            mf = ptr to handle for master folder name string
  277.  *            sv = buf for server volume name
  278.  *            zn = buf for server zone
  279.  *            sn = buf for server name
  280.  *            un = buf for user name
  281.  *            pw = buf for password
  282.  * returns:    0 if preferences found and set,
  283.  *            <> 0 on error
  284.  *=========================================================================
  285.  */
  286. static
  287. OSErr
  288. getPrefs (pf, mf, sv, zn, sn, un, pw)
  289.     Str31            pf;
  290.     StringHandle *    mf;
  291.     Str31            sv;
  292.     Str31            zn;
  293.     Str31            sn;
  294.     Str31            un;
  295.     Str31            pw;
  296. {
  297.     Integer        curref;                /* current resource file */
  298.     OSErr        error;
  299.     Handle        h;                    /* handle to resources */
  300.     int            i;                    /* temp counter */
  301.     u_long        now;                /* current time */
  302.     u_long        interval;            /* running interval from prefs */
  303.     Handle        ph;                    /* handle to interval resource */
  304.     Integer        refnum;                /* resource file refnum */
  305.     StringPtr    sp, tp;                /* ptrs to resource strings */
  306.     Integer        vrefnum;            /* resource file vrefnum */
  307.     HParamBlockRec pb;                /* HFS parameter block */
  308.     Str255        s;                    /* temp copy of string */
  309.  
  310.     /*
  311.      * Extract the various preference resources from the preferences file
  312.      */
  313.     error = 0;
  314.     curref = CurResFile ();
  315.     refnum = OpenRFPerm (pf, 0, fsRdWrPerm);
  316.     if (refnum == -1)
  317.         return ResError ();
  318.     /*
  319.      * First get the interval.
  320.      * If it's not time to run yet, exit
  321.      */
  322.     ph = Get1Resource (TYPE_LONG, TIME_INTERVAL);
  323.     if (!ph)
  324.         goto resexit;
  325.     if (SizeResource (ph) < sizeof (interval))
  326.     {
  327.         error = resNotFound;
  328.         goto exit;
  329.     }
  330.     interval = *(u_long *)(*ph);
  331.     GetDateTime ((long *)&now);
  332.     error = GetVRefNum (refnum, &vrefnum);
  333.     if (error)
  334.         goto exit;
  335.     ZERO (pb);
  336.     pb.fileParam.ioNamePtr = pf;
  337.     pb.fileParam.ioVRefNum = vrefnum;
  338.     error = PBHGetFInfo (&pb, false);
  339.     if (error)
  340.         goto exit;
  341.     if ((u_long) pb.fileParam.ioFlMdDat + interval > now)
  342.     {
  343.         error = 1;                /* not time yet */
  344.         goto exit;
  345.     }
  346.  
  347.     /*
  348.      * Go ahead and extract the remaining preference strings
  349.      */
  350.     h = Get1Resource ('STR ', STR_MASTF);
  351.     if (!h)
  352.         goto resexit;
  353.     /*
  354.      * The master folder STR is a complete path.
  355.      * We also want the first component.
  356.      */
  357.     sp = (StringPtr)(*h);
  358.     COPYPS (sp, s);
  359.     for (i = s[0]; i > 0; i--)
  360.         if (s[i] == ':')
  361.             s[0] = i-1;
  362.     if (s[0] > 31)
  363.         goto badstring;
  364.     *mf = (StringHandle) h;
  365.     DetachResource(h);
  366.     COPYPS (s, sv);
  367.  
  368.     h = Get1Resource ('STR ', STR_ZONE);
  369.     if (h)                        /* zone is optional */
  370.     {
  371.         sp = (StringPtr)(*h);
  372.         if (sp[0] > 31)
  373.             goto badstring;
  374.         COPYPS (sp, zn);
  375.         ReleaseResource (h);
  376.     }
  377.     else
  378.         zn[0] = 0;
  379.  
  380.     h = Get1Resource ('STR ', STR_SRVR);
  381.     if (!h)
  382.         goto resexit;
  383.     sp = (StringPtr)(*h);
  384.     if (sp[0] > 31)
  385.         goto badstring;
  386.     COPYPS (sp, sn);
  387.     ReleaseResource (h);
  388.  
  389.     h = Get1Resource ('STR ', STR_USER);
  390.     if (h)                        /* user is optional */
  391.     {
  392.         sp = (StringPtr)(*h);
  393.         if (sp[0] > 31)
  394.             goto badstring;
  395.         COPYPS (sp, un);
  396.         ReleaseResource (h);
  397.     }
  398.     else
  399.         un[0] = 0;
  400.  
  401.     h = Get1Resource ('STR ', STR_PASS);
  402.     if (h)                        /* password is optional */
  403.     {
  404.         sp = (StringPtr)(*h);
  405.         if (sp[0] > 31)
  406.             goto badstring;
  407.         COPYPS (sp, pw);
  408.         ReleaseResource (h);
  409.     }
  410.     else
  411.         pw[0] = 0;
  412.     /*
  413.      * "Change" a resource to update the mod time so we don't
  414.      * get in a boot/run/reboot loop
  415.      */
  416.     ChangedResource (ph);
  417.     WriteResource (ph);
  418.     goto exit;
  419.  
  420. resexit:
  421.     error = ResError ();
  422.     if (!error)
  423.         error = resNotFound;
  424.     goto exit;
  425.  
  426. badstring:
  427.     ReleaseResource (h);
  428.     error = bdNamErr;
  429.  
  430. exit:
  431.     if (ph)
  432.         ReleaseResource (ph);
  433.     if (refnum != curref)
  434.     {
  435.         (void) CloseResFile (refnum);
  436.         (void) UseResFile (curref);
  437.     }
  438.     return error;
  439. }
  440.  
  441.  
  442.  
  443.  
  444. /*
  445.  *=========================================================================
  446.  * getPrefsName (ap, pf) - extract preferences file name from appl file
  447.  * entry:    ap = name of RevRdist application in current directory
  448.  *            pf = buf for prefs file name
  449.  * returns    0 if pf set,
  450.  *            <> 0 on error
  451.  *=========================================================================
  452.  */
  453. static
  454. OSErr
  455. getPrefsName (ap, pf)
  456.     Str31        ap;
  457.     Str31        pf;
  458. {
  459.     Integer        curref;                /* current resource file */
  460.     OSErr        error;
  461.     Handle        h;
  462.     Integer        refnum;                /* resource file refnum */
  463.     StringPtr    sp;
  464.  
  465.     /*
  466.      * We just extract the STR_PREFS resource from the RevRdist
  467.      * application to get the name of the its default preferences file.
  468.      */
  469.     error = 0;
  470.     curref = CurResFile ();
  471.     refnum = OpenRFPerm (ap, 0, fsRdPerm);
  472.     if (refnum == -1)
  473.         return (ResError ());
  474.     h = Get1Resource ('STR ', STR_PREFS);
  475.     if (h)
  476.     {
  477.         sp = (StringPtr)(*h);
  478.         if (sp[0] < 32)
  479.         {
  480.             COPYPS (sp, pf);
  481.             ReleaseResource (h);
  482.             ShowINIT (RSRC_INITICON);
  483.         }
  484.         else
  485.             error = bdNamErr;
  486.     }
  487.     else
  488.         error = ResError ();
  489.     if (refnum != curref)
  490.     {
  491.         (void) CloseResFile (refnum);
  492.         (void) UseResFile (curref);
  493.     }
  494.     return error;
  495. }
  496.  
  497.  
  498.  
  499.  
  500. /*
  501.  *=========================================================================
  502.  * mountsvr (sv, zn, sn, un, pw) - make sure server volume is mounted
  503.  * entry:    sv = name of desired server volume
  504.  *            zn = AppleShare zone of server
  505.  *            sn = AppleShare name of server node
  506.  *            un = user name to use to log into node
  507.  *            pw = password for login
  508.  * returns:    0 if volume mounted
  509.  *            <> 0 on error
  510.  *=========================================================================
  511.  */
  512. static
  513. OSErr
  514. mountsvr (sv, zn, sn, un, pw)
  515.     Str31        sv;
  516.     Str31        zn;
  517.     Str31        sn;
  518.     Str31        un;
  519.     Str31        pw;
  520. {
  521.     OSErr            error;
  522.     register Handle    h;                /* temp handle */
  523.     int                i, j;            /* temp index */
  524.     int                pass;            /* try counter */
  525.     Handle            xh;                /* handle to XCMD */
  526.     XCmdBlock        cb;                /* XCMD parameter block */
  527.     HParamBlockRec    pb;                /* HFS parameter block */
  528.     Str255            name;
  529.  
  530.     h = (Handle) 2;                    /* set non-zero */
  531.     for (pass = 1; pass <= 2; pass++)
  532.     {
  533.         /*
  534.          * Scan the mounted volumes looking for the server volume
  535.          */
  536.         ZERO (pb);
  537.         pb.volumeParam.ioNamePtr = name;
  538.         for (i = 1, error = 0; ! error; i++)
  539.         {
  540.             name[0] = 0;
  541.             pb.volumeParam.ioVRefNum = 0;
  542.             pb.volumeParam.ioVolIndex = i;
  543.             error = PBHGetVInfo (&pb, false);
  544.             if (RelString (sv, name, false, true) == 0)
  545.                 return 0;            /* found it */
  546.         }
  547.         /*
  548.          * Searched all volumes without finding it.
  549.          * Use the Apple Mount XCMD to try to mount the volume from
  550.          * an AppleShare server.
  551.          */
  552.         xh = GetResource ('XCMD', RSRC_MOUNT);
  553.         if (! xh)
  554.             return (ResError ());
  555.         ZERO (cb);
  556.         /*
  557.          * Set calling arg list into XCMD param block
  558.          */
  559.         error = memFullErr;
  560.         i = 0;
  561.         cb.params[i++] = h = ptoch (zn);    /* zone */
  562.         if (!h)
  563.             goto failed;
  564.         cb.params[i++] = h = ptoch (sn);    /* server */
  565.         if (!h)
  566.             goto failed;
  567.         cb.params[i++] = h = ptoch (sv);    /* volume */
  568.         if (!h)
  569.             goto failed;
  570.         if (un[0])                            /* user, if not empty */
  571.         {
  572.             cb.params[i++] = h = ptoch (un);
  573.             if (!h)
  574.                 goto failed;
  575.             if (pw[0])                        /* password, if not empty */
  576.             {
  577.                 cb.params[i++] = h = ptoch (pw);
  578.                 if (!h)
  579.                     goto failed;
  580.             }
  581.         }
  582.         error = 0;
  583.         cb.paramCount = i;
  584.         cb.entryPoint = (ProcPtr) callback;
  585.         HLock (xh);
  586.         (*(ProcPtr)(*xh)) (&cb);            /* call the XCMD */
  587.         /*
  588.          * dispose of our strings, etc.
  589.          */
  590.         HUnlock (xh);
  591. failed:
  592.         for (--i; i >= 0; --i)
  593.             DisposHandle (cb.params[i]);
  594.         h = cb.returnValue;                    /* check the result */
  595.         if (h && *h && **h)
  596.             error = fnfErr;
  597.         if (cb.returnValue)
  598.             DisposHandle (cb.returnValue);
  599.         ReleaseResource (xh);
  600.         if (error)
  601.             break;
  602.     }
  603.     return error;
  604. }
  605.  
  606.  
  607.  
  608. /*
  609.  *=========================================================================
  610.  * ptoch (ps) - copy pascal string to c string in new handle
  611.  * entry:    ps = ptr to pascal string
  612.  * returns:    handle to null-terminated copy of string
  613.  *            0 if cannot allocate handle
  614.  *=========================================================================
  615.  */
  616. static
  617. Handle
  618. ptoch (ps)
  619. register unsigned char *ps;
  620. {
  621. register Handle h;
  622. register int    i;
  623. register unsigned char *s;
  624.  
  625.     i = ps[0];
  626.     h = NewHandle ((Size) (i + 1));
  627.     if (h)
  628.     {
  629.         for (s = (unsigned char *)(*h); i; i--)
  630.             *s++ = *++ps;
  631.         *s = 0;
  632.     }
  633.     return h;
  634. }